package util;

import excecao.InfraestruturaException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JPAUtil {

    private static EntityManagerFactory emf = null;
    private static final ThreadLocal<EntityManager> threadEntityManager = new ThreadLocal<EntityManager>();
    private static final ThreadLocal<EntityTransaction> threadTransaction = new ThreadLocal<EntityTransaction>();

    public static void startUp() {
        emf = Persistence.createEntityManagerFactory("treinamento");
    }

    public static void startUp(String persistenceUnitName) {
        emf = Persistence.createEntityManagerFactory(persistenceUnitName);
    }

    public static EntityManager getEntityManager() {
        EntityManager s = threadEntityManager.get();
        try {
            if (s == null) {
                s = emf.createEntityManager();
                threadEntityManager.set(s);
            }
        } catch (RuntimeException ex) {
            throw new InfraestruturaException(ex);
        }
        return s;
    }

    public static void closeEntityManager() {
        try {
            EntityManager s = threadEntityManager.get();
            threadEntityManager.set(null);
            if (s != null && s.isOpen()) {
                s.close();
            }

            EntityTransaction tx = threadTransaction.get();
            if (tx != null && tx.isActive()) {
                rollbackTransaction();
                throw new RuntimeException("EntityManager sendo fechado com transação ativa.");
            }
        } catch (RuntimeException ex) {
            throw new InfraestruturaException(ex);
        }
    }

    public static void beginTransaction() {
        EntityTransaction tx = threadTransaction.get();
        try {
            if (tx == null) {
                tx = getEntityManager().getTransaction();
                tx.begin();
                threadTransaction.set(tx);
            }
        } catch (RuntimeException ex) {
            throw new InfraestruturaException(ex);
        }
    }

    public static boolean isTransacaoAtiva() {
        EntityTransaction tx = threadTransaction.get();
        return (tx != null && tx.isActive());
    }

    public static void commitTransaction() {
        EntityTransaction tx = threadTransaction.get();
        if (tx != null && tx.isActive()) {
            tx.commit();
        }
        threadTransaction.set(null);
    }

    public static void rollbackTransaction() {
        EntityTransaction tx = threadTransaction.get();
        try {
            threadTransaction.set(null);
            if (tx != null && tx.isActive()) {
                tx.rollback();
            }
        } catch (RuntimeException ex) {
            throw new InfraestruturaException(ex);
        } finally {
            closeEntityManager();
        }
    }
}
